<?php

	namespace org\tekuna\framework;


	use org\tekuna\base\Tekuna;
	
	use org\tekuna\core\application\Application;
	use org\tekuna\core\context\Context;
	use org\tekuna\core\event\Event;
	use org\tekuna\core\event\AbstractEventListener;
	
	use org\tekuna\framework\action\ActionEvent;
	use org\tekuna\framework\interceptor\InterceptorProcessor;
	use org\tekuna\framework\response\ResponseEvent;
	use org\tekuna\framework\response\ResponseException;
	

	class ActionListener extends AbstractEventListener {

		private $objLogger;


		public function __construct() {

			$this -> objLogger = Tekuna :: getLogger(__CLASS__);
		}

		public function handlesEvent(Event $objEvent) {
			
			return $objEvent instanceof ActionEvent;
		}
		
		public function handleEvent(Event $objEvent) {

			// build interceptor chain
			$objIP = new InterceptorProcessor($this -> getApplicationContext());
			$objInvocationChain = $objIP -> buildInvocationChain($objEvent);

			// start output buffering
			if (Application :: isHttpRequest()) {
				
				ob_start();
			}
			
			// run interceptor chain and the action at the end
			$objResponse = $objInvocationChain -> invokeNext();

			// send response event if the action requires a response 
			if (Application :: isHttpRequest()) {
				
				// end output buffering
				$sDirectOutput = ob_get_contents();
				ob_end_clean();
				
				// punish direct outputs with an exception
				if ($sDirectOutput != '') {
					
					$this -> objLogger -> warn("Detected direct output: $sDirectOutput");
					throw new ResponseException("There where ". strlen($sDirectOutput) ." bytes of direct output (e.g. through echo, print, print_r, var_dump) discovered during interceptors and action running. Every output of HTTP requests must be encapsulated within a Response object (e.g. org\\tekuna\\framework\\response\\http\\ContentResponse). To capture direct outputs of third-party libraries, use the output buffering functions (ob_start(), ob_get_contents(), ob_end_clean()) to capture the output and append it to a regurlar Response object.");
				}
			}

			$this -> getApplicationContext() -> getEventManager() -> triggerEvent(new ResponseEvent($objResponse));
		}
	}